Load data

Maps data

We use three different shapefiles for the continental U.S. land mass, the State waters of maine, new hampshire, massachusets, connecticut, rhode island, new york, new jersey, delaware, maryland, virginia, north carolina and the North East EEZ.

1.- Land shapefile; covers the US land territory for visualization. Data provided from the map package.

2.- State waters; covers the state waters of the NE US states. Data from data.gov.

License: No license information was provided. If this work was prepared by an officer or employee of the United States government as part of that person’s official duties it is considered a U.S. Government Work.

3.- EEZ shapefile; Used the Sea Around Us shapefle updated to June 2016.

unique(land_sf$ID)

Spatial component

Create base shapefile for computation

As a first step we need to divide the NE US EEZ among the different states. For that we expanded state waters up to the 200 nautical miles to then estimate the percentage that each expanded-state-waters occupied. Note that in all cases these areas overlapped and percentages accounted for it. We did this by following these steps:

    1. Expand state waters using a buffer
    1. Grid that buffer on a 0.3 resolution
    1. Crop the buffer to the EEZ

1. Expand Spatial regions (a.k.a buffers)

We set a buffer of 410000 m (410 km, ~ 221 nm) that overshoots the EEZ a bit, but is eventually cropped


# Buffer state waters
state_bf = st_buffer(state_sf, 410000) %>% 
  st_transform(4326) %>% # to match shape
  st_set_crs(4326)

# ------------------------------ #
# Testing and visualizing the buffer 
# ------------------------------ #

state_bf_plot <- ggplot() +
  geom_sf(data = eez_sf, aes(), fill = NA) +
  geom_sf(data = state_bf, aes(color = state), fill = NA)
#   

# ggsave("../Results/Partial/state_waters_buffer.png",state_bf_plot)

# ------------------------------ #

state_bf_plot

2. Expand grid within buffer

Here we expand a grid within the buffer so we can estimate the proportion of each state

2.1 Merge grid and buffers

Once we have a gridded area, we converted the grid to a sf so we can merge it with the buffered states and finally filter out everything outside the states polygon


# ---------------- #
# Convert grid to sf
# ---------------- #
grid_sf <- st_as_sf(ne_grid,
             coords = c("lon", "lat"),
             crs = 4326) %>% 
  st_join(state_bf) %>% 
  filter(!is.na(state))

# Create data frame for future computations
# Note, will be used in next chunk
grid_bf_dt <- as.data.frame(grid_sf) %>%
    select(index,state)
    # group_by(state) %>% 
    # summarise(length(index))


# ---------------- #
# [TEST] 
# Visualization of grid
# ---------------- #

gridExtra::grid.arrange(
  # Overall (overlapping) position
  ggplot(grid_sf) +
    geom_sf(aes(color = state), alpha = 0.3) +
    geom_sf(data = eez_sf, aes(),fill =NA) + 
    theme(legend.position = ""),
  # Showing each state separatley
  ggplot() +
    geom_sf(data = grid_sf, aes(color = state),size = 0.1, alpha = 0.3) +
    facet_wrap(~state) +
    theme(legend.position = "top"),
  nrow = 1)

3. Crop buffers to EEZ

Finally, we crop the grided buffers to within the EEZ to capture the actual water space.

Note: This step takes quite a while because of the size of the EEZ shapefile. No, you cannot use st_simplify() here

Interpolation rutine

Here we interpolate the survey data within the previously created grid.

  • We removed cases where wtcpue < 0

Function for interpolation

This is the main function used to interpolate the data per year. It follows a Triangular Irregular Surface method using the interp::interp() function.


tis <- function(input_data, grid, yr, taxa, reg){
  
  # --------------- #
  # Testing
  # print(paste(yr))
  # yr = 1976
  # --------------- #
  
  # Filter data
  data <- input_data %>% 
    filter(year == yr,
           spp == taxa,
           region == reg
    ) %>% 
    # Average duplicated hauls in the same spot
    group_by(region,year,spp,lat,lon) %>%
    summarise_at(vars(wtcpue),
                 mean,na.rm = T) %>%
    filter(wtcpue > 0)
    
  # Only interpolate cases where there is more than 3 rows
  # Marked by the function 
    if(nrow(data) <= 3){
      fit_tin <- tibble()
    }else{
      
      # Triangular Irregular Surface
      fit_tin <- interp::interp( # using {interp}
        x = data$lon,           # the function actually accepts coordinate vectors
        y = data$lat,
        z = data$wtcpue,
        xo = grid$lon,     # here we already define the target grid
        yo = grid$lat,
        output = "points"
      ) %>% 
        bind_cols() %>% 
        bind_cols(grid) %>%
        mutate(year = yr,
               region = reg,
               spp = taxa) %>% 
        select(index, state, year, region, spp, lon=x, lat=y, value = z)
      
    }
   
    return(fit_tin)
}

# Test me
# Needs variables in Control panel
# Test no data: "Alosa aestivalis", reg = "Northeast US Fall", yr = 1974 
# tis(input_data = ocean_data, grid = grid_eez_df, taxa = "Illex illecebrosus", reg = "Northeast US Fall", yr = 1973)



# lapply(years,tis,input_data = ocean_data, grid = grid_eez_df, taxa = "Illex illecebrosus", reg = regions[2])

Run function

Ocean adapt data

  • Using only the Northeast US Fall and Spring bottom trawl survey data for now

Control Pannel

Load required data. Note that some of it has been previously created

head(spp)
[1] "Alosa aestivalis"     "Alosa pseudoharengus"
[3] "Alosa sapidissima"    "Amblyraja radiata"   
[5] "Ammodytes dubius"     "Anarhichas lupus"    

Run routine


# single species run
# run_tis(input_data = ocean_data,
#         grid = grid_eez_df,
#         years = years,
#         reg = regions,
#         taxa = "Illex illecebrosus"
# )


# Run them all in parallel
parallel::mclapply(spp,
                   run_tis, 
                   input_data = ocean_data,
                   grid = grid_eez_df,
                   years = years,
                   reg = regions
)

Results

Points

Map

Area plot

This graph shows the proportion of each State over time

Area plot (running)

This graph shows the proportion of each State smoothed over a 10 years running mean. It helps seeing the trends better (I Think…)

LS0tCnRpdGxlOiAiU3BhdGlhbCBBbmFseXNpcyIKb3V0cHV0OiAKICMgaHRtbF9kb2N1bWVudAogIGh0bWxfbm90ZWJvb2s6CiAgZmlnX3dpZHRoOiA2CiAgZmlnX2hlaWdodDogNAogIHRvYzogZmFsc2UKICB0b2NfZGVwdGg6IDMKICBjb2RlX2ZvbGRpbmc6IGhpZGUKICB0b2NfZmxvYXQ6CiAgICBjb2xsYXBzZWQ6IGZhbHNlCi0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmxpYnJhcnkoTXlGdW5jdGlvbnMpCk15RnVuY3Rpb25zOjpteV9saWIoYygiZ2dtYXAiLCJzZiIsInRpZHl2ZXJzZSIsInRvb2xzIiwicmVhZHIiLCJkYXRhLnRhYmxlIiwibWFwcyIsInZpcmlkaXMiLCJ3ZXNhbmRlcnNvbiIsImtuaXRyIiwia2FibGVFeHRyYSIsInBsb3RseSIpKQpgYGAKCgojIExvYWQgZGF0YQoKIyMgTWFwcyBkYXRhCgpXZSB1c2UgdGhyZWUgZGlmZmVyZW50IHNoYXBlZmlsZXMgZm9yIHRoZSBjb250aW5lbnRhbCBVLlMuIGxhbmQgbWFzcywgdGhlIFN0YXRlIHdhdGVycyBvZiBtYWluZSwgbmV3IGhhbXBzaGlyZSwgbWFzc2FjaHVzZXRzLCBjb25uZWN0aWN1dCwgcmhvZGUgaXNsYW5kLCBuZXcgeW9yaywgbmV3IGplcnNleSwgZGVsYXdhcmUsIG1hcnlsYW5kLCB2aXJnaW5pYSwgbm9ydGggY2Fyb2xpbmEgYW5kIHRoZSBOb3J0aCBFYXN0IEVFWi4KCjEuLSAqKkxhbmQgc2hhcGVmaWxlOyoqIGNvdmVycyB0aGUgVVMgbGFuZCB0ZXJyaXRvcnkgZm9yIHZpc3VhbGl6YXRpb24uIERhdGEgcHJvdmlkZWQgZnJvbSB0aGUgYG1hcGAgcGFja2FnZS4KCjIuLSAqKlN0YXRlIHdhdGVyczsqKiBjb3ZlcnMgdGhlIHN0YXRlIHdhdGVycyBvZiB0aGUgTkUgVVMgc3RhdGVzLiBEYXRhIGZyb20gW2RhdGEuZ292XShodHRwczovL2NhdGFsb2cuZGF0YS5nb3YvZGF0YXNldC9mZWRlcmFsLWFuZC1zdGF0ZS13YXRlcnMpLiAgCgoqTGljZW5zZTogTm8gbGljZW5zZSBpbmZvcm1hdGlvbiB3YXMgcHJvdmlkZWQuIElmIHRoaXMgd29yayB3YXMgcHJlcGFyZWQgYnkgYW4gb2ZmaWNlciBvciBlbXBsb3llZSBvZiB0aGUgVW5pdGVkIFN0YXRlcyBnb3Zlcm5tZW50IGFzIHBhcnQgb2YgdGhhdCBwZXJzb24ncyBvZmZpY2lhbCBkdXRpZXMgaXQgaXMgY29uc2lkZXJlZCBhIFUuUy4gR292ZXJubWVudCBXb3JrLioKCjMuLSAqKkVFWiBzaGFwZWZpbGU7KiogVXNlZCB0aGUgKlNlYSBBcm91bmQgVXMqIHNoYXBlZmxlIHVwZGF0ZWQgdG8gSnVuZSAyMDE2LgoKYGBge3IgbWFwc19zZiwgZXZhbCA9IFQsIGVjaG8gPSBULCByZXN1bHRzID0gJ2hpZGUnfQoKU3RhdGVzIDwtIGMoIm1haW5lIiwgIm5ldyBoYW1wc2hpcmUiLCAibWFzc2FjaHVzZXR0cyIsICJjb25uZWN0aWN1dCIsICJyaG9kZSBpc2xhbmQiLCAibmV3IHlvcmsiLCAibmV3IGplcnNleSIsICJkZWxhd2FyZSIsICJtYXJ5bGFuZCIsICJ2aXJnaW5pYSIsICJub3J0aCBjYXJvbGluYSIsInBlbm5zeWx2YW5pYSIpIAoKIyBVUyBTdGF0ZSBNYXAgKGxhbmQpCgpsYW5kX3NmIDwtIHN0X2FzX3NmKG1hcCgic3RhdGUiLCBwbG90ID0gRkFMU0UsIGZpbGwgPSBUUlVFKSkgJT4lIAogIGZpbHRlcihJRCAlaW4lIFN0YXRlcykgCgojIGdncGxvdCh1c19tYXApICsKICAjIGdlb21fc2YoKQoKIyBVUyBFRVogbWFwCgojIHBhdGhfd29ybGQgPC0gTXlGdW5jdGlvbnM6Om15X3BhdGgoIkciLCBleHRyYV9wYXRoID0gIlNwYXRpYWwvU0FVL1NBVV9TaGFwZWZpbGUiKQpwYXRoX3dvcmxkIDwtICJ+L0Rvd25sb2Fkcy9TQVVfU2hhcGVmaWxlIgoKIyBUaGUgRmlsZQpmbmFtX3dvcmxkIDwtICJTQVVFRVpfSnVseTIwMTUuc2hwIgoKIyBMb2FkIGl0IQplZXpfc2YgPC0gc3RfcmVhZChkc24gPSBwYXRoX3dvcmxkLAogICAgICAgICAgICAgICAgICAgICAgICBsYXllciA9ZmlsZV9wYXRoX3NhbnNfZXh0KGZuYW1fd29ybGQpKSAlPiUgCiAgcmVuYW1lKGVlel9uYW1lID0gTmFtZSkgJT4lIAogIHN0X3RyYW5zZm9ybShjcnMgPSA0MzI2KSAlPiUgIyA0MzI2CiAgc3Rfc2ltcGxpZnkocHJlc2VydmVUb3BvbG9neSA9IFRSVUUsIGRUb2xlcmFuY2UgPSAxMDAwMCkgJT4lICMwLjEgZm9yIHBhcGVyCiAgZmlsdGVyKGVlel9uYW1lID09ICJVU0EgKEVhc3QgQ29hc3QpIikKCgojIGdncGxvdChlZXpfc2YpICsKIyBnZW9tX3NmKGFlcygpLGZpbGwgPU5BKQoKIyBnZ3Bsb3QoKSArCiMgICBnZW9tX3NmKGRhdGEgPSBXb3JsZF9lZXpfc2YsIGFlcygpLCBjb2xvciA9ICJyZWQiKSArCiMgICBnZW9tX3NmKGRhdGEgPSB1c19tYXAsIGFlcygpLCBjb2xvciA9ICJibHVlIikKCiMgVVMgc3RhdGUgd2F0ZXJzCiMgaHR0cHM6Ly9jYXRhbG9nLmRhdGEuZ292L2RhdGFzZXQvZmVkZXJhbC1hbmQtc3RhdGUtd2F0ZXJzCgojIHVzX3N0YXRlX3cgPC0gcmdkYWw6OnJlYWRPR1IoZHNuID0gIn4vRG93bmxvYWRzL0ZlZGVyYWxBbmRTdGF0ZVdhdGVycy9GZWRlcmFsQW5kU3RhdGVXYXRlcnMuZ2RiIikKc3RhdGVfc2YgPC0gIHN0X3JlYWQoIn4vRG93bmxvYWRzL0ZlZGVyYWxBbmRTdGF0ZVdhdGVycy9GZWRlcmFsQW5kU3RhdGVXYXRlcnMuZ2RiIikgJT4lCiAgamFuaXRvcjo6Y2xlYW5fbmFtZXMoKSAlPiUgCiAgbXV0YXRlKGp1cmlzZGljdGkgPSBzdHJfdG9fbG93ZXIoanVyaXNkaWN0aSkpICU+JSAKICBmaWx0ZXIoanVyaXNkaWN0aSAlaW4lIFN0YXRlcykgJT4lIAogIHJlbmFtZShzdGF0ZSA9IGp1cmlzZGljdGkpICU+JSAKICAjIHN0X3RyYW5zZm9ybShjcnMgPSA0MzI2KSAgIyBmb3IgbWF0Y2hpbmcgcHJvamVjdGlvbnMKICBzdF9zaW1wbGlmeShwcmVzZXJ2ZVRvcG9sb2d5ID0gVFJVRSwgZFRvbGVyYW5jZSA9IDEwMDAwKSAjMC4xIGZvciBwYXBlcgoKCmdyaWRfc2YgPC0gIHN0X3JlYWQoIi9Wb2x1bWVzL0VudGVycHJpc2UvRGF0YS9BY3Jvc3NCb3VuZGFyaWVzL0RhdGEvU3BhdGlhbC9ncmlkX3NmL2dyaWRfZWV6X3NmLnNocCIpCgp1bmlxdWUobGFuZF9zZiRJRCkKCmBgYAoKCiMjIFNwYXRpYWwgY29tcG9uZW50CgojIyMgQ3JlYXRlIGJhc2Ugc2hhcGVmaWxlIGZvciBjb21wdXRhdGlvbgoKQXMgYSBmaXJzdCBzdGVwIHdlIG5lZWQgdG8gZGl2aWRlIHRoZSBORSBVUyBFRVogYW1vbmcgdGhlIGRpZmZlcmVudCBzdGF0ZXMuIEZvciB0aGF0IHdlIGV4cGFuZGVkIHN0YXRlIHdhdGVycyB1cCB0byB0aGUgMjAwIG5hdXRpY2FsIG1pbGVzIHRvIHRoZW4gZXN0aW1hdGUgdGhlIHBlcmNlbnRhZ2UgdGhhdCBlYWNoIGV4cGFuZGVkLXN0YXRlLXdhdGVycyBvY2N1cGllZC4gTm90ZSB0aGF0IGluIGFsbCBjYXNlcyB0aGVzZSBhcmVhcyBvdmVybGFwcGVkIGFuZCBwZXJjZW50YWdlcyBhY2NvdW50ZWQgZm9yIGl0LiBXZSBkaWQgdGhpcyBieSBmb2xsb3dpbmcgdGhlc2Ugc3RlcHM6CgotIDEuIEV4cGFuZCBzdGF0ZSB3YXRlcnMgdXNpbmcgYSBidWZmZXIKCi0gMi4gR3JpZCB0aGF0IGJ1ZmZlciBvbiBhIDAuMyByZXNvbHV0aW9uCgotIDMuIENyb3AgdGhlIGJ1ZmZlciB0byB0aGUgRUVaCgojIyMjIDEuIEV4cGFuZCBTcGF0aWFsIHJlZ2lvbnMgKGEuay5hICBidWZmZXJzKQoKV2Ugc2V0IGEgYnVmZmVyIG9mICo0MTAwMDAqIG0gKDQxMCBrbSwgfiAyMjEgbm0pIHRoYXQgb3ZlcnNob290cyB0aGUgRUVaIGEgYml0LCBidXQgaXMgZXZlbnR1YWxseSBjcm9wcGVkCgpgYGB7ciBidWZmZXIsIGV2YWwgPSBULCBlY2hvID0gVH0KCiMgQnVmZmVyIHN0YXRlIHdhdGVycwpzdGF0ZV9iZiA9IHN0X2J1ZmZlcihzdGF0ZV9zZiwgNDEwMDAwKSAlPiUgCiAgc3RfdHJhbnNmb3JtKDQzMjYpICU+JSAjIHRvIG1hdGNoIHNoYXBlCiAgc3Rfc2V0X2Nycyg0MzI2KQoKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gIwojIFRlc3RpbmcgYW5kIHZpc3VhbGl6aW5nIHRoZSBidWZmZXIgCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICMKCnN0YXRlX2JmX3Bsb3QgPC0gZ2dwbG90KCkgKwogIGdlb21fc2YoZGF0YSA9IGVlel9zZiwgYWVzKCksIGZpbGwgPSBOQSkgKwogIGdlb21fc2YoZGF0YSA9IHN0YXRlX2JmLCBhZXMoY29sb3IgPSBzdGF0ZSksIGZpbGwgPSBOQSkKIyAgIAoKIyBnZ3NhdmUoIi4uL1Jlc3VsdHMvUGFydGlhbC9zdGF0ZV93YXRlcnNfYnVmZmVyLnBuZyIsc3RhdGVfYmZfcGxvdCkKCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICMKCnN0YXRlX2JmX3Bsb3QKCmBgYAoKIyMjIyAyLiBFeHBhbmQgZ3JpZCB3aXRoaW4gYnVmZmVyCgpIZXJlIHdlIGV4cGFuZCBhIGdyaWQgd2l0aGluIHRoZSBidWZmZXIgc28gd2UgY2FuIGVzdGltYXRlIHRoZSBwcm9wb3J0aW9uIG9mIGVhY2ggc3RhdGUKCmBgYHtyIGdyaWRfaW5kZXhpbmcsIGV2YWwgPSBULCBlY2hvID0gVCwgbWVzc2FnZSA9IEYsIHdhcm5pbmcgPSBGfQoKIyBDcmVhdGUgZ3JpZCBvZiB0aGUgcmVnaW9uCmJib3ggPC0gYyhzdF9iYm94KHN0YXRlX2JmKSkKCiMgRXhwYW5kIHRoZSBncmlkCm5lX2dyaWQgPC0gZXhwYW5kLmdyaWQoCiAgICBsb24gPSBzZXEoZnJvbSA9IGJib3hbInhtaW4iXSwgdG8gPSBiYm94WyJ4bWF4Il0sIGJ5ID0gMC4zKSwKICAgIGxhdCA9IHNlcShmcm9tID0gYmJveFsieW1pbiJdLCB0byA9IGJib3hbInltYXgiXSwgYnkgPSAwLjMpCikgJT4lIAogIHJvd2lkX3RvX2NvbHVtbigiaW5kZXgiKQoKIyAtLS0tLS0tLS0tLSAjCiMgW1RFU1RdIFBsb3QgYWxsIGxheWVycwojIC0tLS0tLS0tLS0tICMKCiMgTG9va3MgZ29vZApzdGF0ZV9zZiAlPiUKICBzdF90cmFuc2Zvcm0oNDMyNikgJT4lICMgdG8gbWF0Y2ggc2hhcGUKICBzdF9zZXRfY3JzKDQzMjYpICU+JQogIHN0X3NpbXBsaWZ5KHByZXNlcnZlVG9wb2xvZ3kgPSBUUlVFLCBkVG9sZXJhbmNlID0gMTAwMDApICU+JQogIGdncGxvdCgpICsKICBnZW9tX3NmKGFlcyhjb2xvciA9IHN0YXRlKSkrCiAgIyBnZW9tX3NmKGRhdGEgPSBlZXpfc2YsIGFlcygpLGZpbGwgPU5BKSArCiAgIyBnZ3Bsb3QoKSsKICBnZW9tX3RpbGUoZGF0YSA9IG5lX2dyaWQsCiAgICAgICAgICAgIGFlcygKICAgICAgICAgICAgICB4ID0gbG9uLAogICAgICAgICAgICAgIHkgPSBsYXQKICAgICAgICAgICAgKSwKICAgICAgICAgICAgYWxwaGEgPSAwLjIKICApIAoKCmBgYAoKIyMjIyMgMi4xIE1lcmdlIGdyaWQgYW5kIGJ1ZmZlcnMKCk9uY2Ugd2UgaGF2ZSBhIGdyaWRkZWQgYXJlYSwgd2UgY29udmVydGVkIHRoZSBncmlkIHRvIGEgYHNmYCBzbyB3ZSBjYW4gbWVyZ2UgaXQgd2l0aCB0aGUgYnVmZmVyZWQgc3RhdGVzIGFuZCBmaW5hbGx5IGZpbHRlciBvdXQgZXZlcnl0aGluZyBvdXRzaWRlIHRoZSBzdGF0ZXMgcG9seWdvbgoKYGBge3IgZ3JpZF9idWZfbWVyZ2UsIGV2YWwgPSBULCBlY2hvID0gVCwgbWVzc2FnZSA9IEYsIHdhcm5pbmcgPSBGLCBmaWcud2lkdGggPSAxMH0KCiMgLS0tLS0tLS0tLS0tLS0tLSAjCiMgQ29udmVydCBncmlkIHRvIHNmCiMgLS0tLS0tLS0tLS0tLS0tLSAjCmdyaWRfc2YgPC0gc3RfYXNfc2YobmVfZ3JpZCwKICAgICAgICAgICAgIGNvb3JkcyA9IGMoImxvbiIsICJsYXQiKSwKICAgICAgICAgICAgIGNycyA9IDQzMjYpICU+JSAKICBzdF9qb2luKHN0YXRlX2JmKSAlPiUgCiAgZmlsdGVyKCFpcy5uYShzdGF0ZSkpCgojIENyZWF0ZSBkYXRhIGZyYW1lIGZvciBmdXR1cmUgY29tcHV0YXRpb25zCiMgTm90ZSwgd2lsbCBiZSB1c2VkIGluIG5leHQgY2h1bmsKZ3JpZF9iZl9kdCA8LSBhcy5kYXRhLmZyYW1lKGdyaWRfc2YpICU+JQogICAgc2VsZWN0KGluZGV4LHN0YXRlKQogICAgIyBncm91cF9ieShzdGF0ZSkgJT4lIAogICAgIyBzdW1tYXJpc2UobGVuZ3RoKGluZGV4KSkKCgojIC0tLS0tLS0tLS0tLS0tLS0gIwojIFtURVNUXSAKIyBWaXN1YWxpemF0aW9uIG9mIGdyaWQKIyAtLS0tLS0tLS0tLS0tLS0tICMKCmdyaWRFeHRyYTo6Z3JpZC5hcnJhbmdlKAogICMgT3ZlcmFsbCAob3ZlcmxhcHBpbmcpIHBvc2l0aW9uCiAgZ2dwbG90KGdyaWRfc2YpICsKICAgIGdlb21fc2YoYWVzKGNvbG9yID0gc3RhdGUpLCBhbHBoYSA9IDAuMykgKwogICAgZ2VvbV9zZihkYXRhID0gZWV6X3NmLCBhZXMoKSxmaWxsID1OQSkgKyAKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICIiKSwKICAjIFNob3dpbmcgZWFjaCBzdGF0ZSBzZXBhcmF0bGV5CiAgZ2dwbG90KCkgKwogICAgZ2VvbV9zZihkYXRhID0gZ3JpZF9zZiwgYWVzKGNvbG9yID0gc3RhdGUpLHNpemUgPSAwLjEsIGFscGhhID0gMC4zKSArCiAgICBmYWNldF93cmFwKH5zdGF0ZSkgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInRvcCIpLAogIG5yb3cgPSAxKQoKYGBgCgojIyMjIDMuIENyb3AgYnVmZmVycyB0byBFRVoKCkZpbmFsbHksIHdlIGNyb3AgdGhlIGdyaWRlZCBidWZmZXJzIHRvIHdpdGhpbiB0aGUgRUVaIHRvIGNhcHR1cmUgdGhlIGFjdHVhbCB3YXRlciBzcGFjZS4KCipOb3RlOiogVGhpcyBzdGVwIHRha2VzIHF1aXRlIGEgd2hpbGUgYmVjYXVzZSBvZiB0aGUgc2l6ZSBvZiB0aGUgRUVaIHNoYXBlZmlsZS4gTm8sIHlvdSBjYW5ub3QgdXNlIGBzdF9zaW1wbGlmeSgpYCBoZXJlCgpgYGB7ciBidWZmX3RvX2VleiwgZXZhbCA9VCwgZWNobyA9IFQsIG1lc3NhZ2UgPSBGLCB3YXJuaW5nID0gRn0KCgojIEkgZG9uJ3Qga25vdyBob3cgdG8gdW5kbyBzdF9zaW1wbGlmeSBzbyBuZWVkIHRvIHJlLWxvYWQgdGhlIHNoYXBlZmlsZQplZXpfc2YgPC0gc3RfcmVhZChkc24gPSBwYXRoX3dvcmxkLAogICAgICAgICAgICAgICAgICAgICAgICBsYXllciA9ZmlsZV9wYXRoX3NhbnNfZXh0KGZuYW1fd29ybGQpKSAlPiUgCiAgcmVuYW1lKGVlel9uYW1lID0gTmFtZSkgJT4lIAogIHN0X3RyYW5zZm9ybShjcnMgPSA0MzI2KSAlPiUgIyA0MzI2CiAgZmlsdGVyKGVlel9uYW1lID09ICJVU0EgKEVhc3QgQ29hc3QpIikKCiMgR2V0IHRoZSBvdmVybGFwcGluZyBzZWdtZW50cwpncmlkX2Vlel9zZiA8LSBzdF9pbnRlcnNlY3Rpb24oZ3JpZF9zZixlZXpfc2YpCgojIHdyaXRlX3NmKGdyaWRfZWV6X3NmLCBwYXN0ZTAobXlfcGF0aCgiRCIsICJTcGF0aWFsIiksImdyaWRfZWV6X3NmLnNocCIpKQoKIyBHZXQgZmluYWwgZGYgd2l0aCBpbmRleApncmlkX2Vlel9kZiA8LSBhcy5kYXRhLmZyYW1lKGdyaWRfZWV6X3NmKSAlPiUKICBzZWxlY3Qoc3RhdGUsaW5kZXgpICU+JSAKICBsZWZ0X2pvaW4obmVfZ3JpZCwgCiAgICAgICAgICAgIGJ5ID0gImluZGV4IikKCiMgd3JpdGVfY3N2KGdyaWRfZWV6X2RmLCBwYXN0ZTAobXlfcGF0aCgiUiIsICJQYXJ0aWFsIiksImdyaWRfZWV6X2RmLmNzdiIpKQoKIyBQbG90IHRvIG1ha2Ugc3VyZSBtYWtlcyBzZW5zZSAoUGljYXNzbyBzeWxlKQpncmlkX2Vlel9zZiAlPiUKICBzdF9zaW1wbGlmeShwcmVzZXJ2ZVRvcG9sb2d5ID0gVFJVRSwgZFRvbGVyYW5jZSA9IDEwMDAwKSAlPiUgIzAuMSBmb3IgcGFwZXIKICBnZ3Bsb3QoKSArCiAgZ2VvbV9zZihhZXMoY29sb3IgPSBzdGF0ZSksIGFscGhhID0gMC4zKQoKYGBgCgojIyBJbnRlcnBvbGF0aW9uIHJ1dGluZQoKSGVyZSB3ZSBbaW50ZXJwb2xhdGVdKGh0dHBzOi8vc3dpbGtlLWdlb3NjaWVuY2UubmV0L3Bvc3Qvc3BhdGlhbF9pbnRlcnBvbGF0aW9uLykgdGhlIHN1cnZleSBkYXRhIHdpdGhpbiB0aGUgcHJldmlvdXNseSBjcmVhdGVkIGdyaWQuCgotIFdlIHJlbW92ZWQgY2FzZXMgd2hlcmUgYHd0Y3B1ZSA8IDBgCgojIyMgRnVuY3Rpb24gZm9yIGludGVycG9sYXRpb24KClRoaXMgaXMgdGhlIG1haW4gZnVuY3Rpb24gdXNlZCB0byBpbnRlcnBvbGF0ZSB0aGUgZGF0YSBwZXIgeWVhci4gSXQgZm9sbG93cyBhIFRyaWFuZ3VsYXIgSXJyZWd1bGFyIFN1cmZhY2UgbWV0aG9kIHVzaW5nIHRoZSBgaW50ZXJwOjppbnRlcnAoKWAgZnVuY3Rpb24uCgpgYGB7ciBpbnRlcnBvbF9mdW5jdGlvbiwgZXZhbCA9IFQsIGVjaG8gPSBUfQoKdGlzIDwtIGZ1bmN0aW9uKGlucHV0X2RhdGEsIGdyaWQsIHlyLCB0YXhhLCByZWcpewogIAogICMgLS0tLS0tLS0tLS0tLS0tICMKICAjIFRlc3RpbmcKICAjIHByaW50KHBhc3RlKHlyKSkKICAjIHlyID0gMTk3NgogICMgLS0tLS0tLS0tLS0tLS0tICMKICAKICAjIEZpbHRlciBkYXRhCiAgZGF0YSA8LSBpbnB1dF9kYXRhICU+JSAKICAgIGZpbHRlcih5ZWFyID09IHlyLAogICAgICAgICAgIHNwcCA9PSB0YXhhLAogICAgICAgICAgIHJlZ2lvbiA9PSByZWcKICAgICkgJT4lIAogICAgIyBBdmVyYWdlIGR1cGxpY2F0ZWQgaGF1bHMgaW4gdGhlIHNhbWUgc3BvdAogICAgZ3JvdXBfYnkocmVnaW9uLHllYXIsc3BwLGxhdCxsb24pICU+JQogICAgc3VtbWFyaXNlX2F0KHZhcnMod3RjcHVlKSwKICAgICAgICAgICAgICAgICBtZWFuLG5hLnJtID0gVCkgJT4lCiAgICBmaWx0ZXIod3RjcHVlID4gMCkKICAgIAogICMgT25seSBpbnRlcnBvbGF0ZSBjYXNlcyB3aGVyZSB0aGVyZSBpcyBtb3JlIHRoYW4gMyByb3dzCiAgIyBNYXJrZWQgYnkgdGhlIGZ1bmN0aW9uIAogICAgaWYobnJvdyhkYXRhKSA8PSAzKXsKICAgICAgZml0X3RpbiA8LSB0aWJibGUoKQogICAgfWVsc2V7CiAgICAgIAogICAgICAjIFRyaWFuZ3VsYXIgSXJyZWd1bGFyIFN1cmZhY2UKICAgICAgZml0X3RpbiA8LSBpbnRlcnA6OmludGVycCggIyB1c2luZyB7aW50ZXJwfQogICAgICAgIHggPSBkYXRhJGxvbiwgICAgICAgICAgICMgdGhlIGZ1bmN0aW9uIGFjdHVhbGx5IGFjY2VwdHMgY29vcmRpbmF0ZSB2ZWN0b3JzCiAgICAgICAgeSA9IGRhdGEkbGF0LAogICAgICAgIHogPSBkYXRhJHd0Y3B1ZSwKICAgICAgICB4byA9IGdyaWQkbG9uLCAgICAgIyBoZXJlIHdlIGFscmVhZHkgZGVmaW5lIHRoZSB0YXJnZXQgZ3JpZAogICAgICAgIHlvID0gZ3JpZCRsYXQsCiAgICAgICAgb3V0cHV0ID0gInBvaW50cyIKICAgICAgKSAlPiUgCiAgICAgICAgYmluZF9jb2xzKCkgJT4lIAogICAgICAgIGJpbmRfY29scyhncmlkKSAlPiUKICAgICAgICBtdXRhdGUoeWVhciA9IHlyLAogICAgICAgICAgICAgICByZWdpb24gPSByZWcsCiAgICAgICAgICAgICAgIHNwcCA9IHRheGEpICU+JSAKICAgICAgICBzZWxlY3QoaW5kZXgsIHN0YXRlLCB5ZWFyLCByZWdpb24sIHNwcCwgbG9uPXgsIGxhdD15LCB2YWx1ZSA9IHopCiAgICAgIAogICAgfQogICAKICAgIHJldHVybihmaXRfdGluKQp9CgojIFRlc3QgbWUKIyBOZWVkcyB2YXJpYWJsZXMgaW4gQ29udHJvbCBwYW5lbAojIFRlc3Qgbm8gZGF0YTogIkFsb3NhIGFlc3RpdmFsaXMiLCByZWcgPSAiTm9ydGhlYXN0IFVTIEZhbGwiLCB5ciA9IDE5NzQgCiMgdGlzKGlucHV0X2RhdGEgPSBvY2Vhbl9kYXRhLCBncmlkID0gZ3JpZF9lZXpfZGYsIHRheGEgPSAiSWxsZXggaWxsZWNlYnJvc3VzIiwgcmVnID0gIk5vcnRoZWFzdCBVUyBGYWxsIiwgeXIgPSAxOTczKQoKCgojIGxhcHBseSh5ZWFycyx0aXMsaW5wdXRfZGF0YSA9IG9jZWFuX2RhdGEsIGdyaWQgPSBncmlkX2Vlel9kZiwgdGF4YSA9ICJJbGxleCBpbGxlY2Vicm9zdXMiLCByZWcgPSByZWdpb25zWzJdKQoKYGBgCgojIyMgUnVuIGZ1bmN0aW9uCgpgYGB7ciBpbnRlcnBvbF9ydW5fZnVuLCBldmFsID0gVCwgZWNobyA9IFR9CgoKcnVuX3RpcyA8LSBmdW5jdGlvbihpbnB1dF9kYXRhLCBncmlkLCB5ZWFycywgdGF4YSwgcmVnKXsKICAKICAKICAjIFJ1biB0aXMgZm9yIHNwZWNpZXMgYW5kIHN1cnZleXMKICBmb3IociBpbiAxOjIpewogICAgCiAgICBwYXJ0aWFsX2RmIDwtIGJpbmRfcm93cygKICAgICAgbGFwcGx5KHllYXJzLHRpcyxpbnB1dF9kYXRhID0gb2NlYW5fZGF0YSwgZ3JpZCA9IGdyaWRfZWV6X2RmLCB0YXhhID0gdGF4YSwgcmVnID0gcmVnaW9uc1tyXSkKICAgICkKICAgIAogICAgaWYociA9PSAxKXsKICAgICAgaGlzdG9yaWNfdGlmIDwtIHBhcnRpYWxfZGYKICAgIH1lbHNlewogICAgICBoaXN0b3JpY190aWYgPC0gYmluZF9yb3dzKGhpc3RvcmljX3RpZixwYXJ0aWFsX2RmKQogICAgfQogICAgCiAgfQogIAogICMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gIwogICMgU2F2ZSBkYXRhc2V0IHBlciBzcGVjaWVzCiAgIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAjCiAgCiAgIyBTZXQgZmlsZSBuYW1lCiAgbmFtZSA8LSBwYXN0ZTAoInRpZl8iLHN0cl9yZXBsYWNlKHRheGEsIiAiLCJfIiksIi5jc3YiKQogIAogICMgU2V0IHBhdGggbmFtZQogIHNhdmVfcGF0aCA8LSBteV9wYXRoKCJSIiwiUGFydGlhbC9JbnRlcnBvbGF0aW9uIikKICAKICAjIFNldCBjb21wbGV0ZSBwYXRoCiAgc2F2ZV9uYW1lIDwtIHBhc3RlMChzYXZlX3BhdGgsbmFtZSkKICAKICAjIENyZWF0ZSBmb2xkZXIgaWYgaXQgZG9lcyBub3QgZXhpc3QKICBpZihmaWxlLmV4aXN0cyhzYXZlX3BhdGgpID09IEYpewogICAgZGlyLmNyZWF0ZShzYXZlX3BhdGgpCiAgfQogIAogICMgIFNhdmUgZmlsZQogIHdyaXRlX2NzdihoaXN0b3JpY190aWYsc2F2ZV9uYW1lKQogIAogIHJldHVybl9tc2cgPC0gcGFzdGUoIkludGVycG9sYXRpb24gZG9uZSBmb3IiLCB0YXhhKQogIAogIHJldHVybihyZXR1cm5fbXNnKQogIAogIAp9CgojIFRlc3QgbWUKICAgICMgcnVuX3RpcyhpbnB1dF9kYXRhID0gb2NlYW5fZGF0YSwgZ3JpZCA9IGdyaWRfZWV6X2RmLCB0YXhhID0gIkNlbnRyb3ByaXN0aXMgc3RyaWF0YSIsIHllYXJzID0geWVhcnMsIHJlZyA9IHJlZ2lvbnMpCgpgYGAKCgojIyMgT2NlYW4gYWRhcHQgZGF0YQoKLSBVc2luZyBvbmx5IHRoZSBOb3J0aGVhc3QgVVMgRmFsbCBhbmQgU3ByaW5nIGJvdHRvbSB0cmF3bCBzdXJ2ZXkgZGF0YSBmb3Igbm93CgpgYGB7ciBkYXRfZXhwbG9kZWQsIGV2YWwgPSBULCBlY2hvID0gRiwgZmlnLndpZHRoID0gOX0KCm9jZWFuX2RhdGEgPC0gcmVhZFJEUygiL1ZvbHVtZXMvRW50ZXJwcmlzZS9EYXRhL3BpbnNreWxhYi1PY2VhbkFkYXB0LTk2NmFkZjAvZGF0YV9jbGVhbi9kYXRfZXhwbG9kZWQucmRzIikgIyU+JSAKICAjIGZpbHRlcihzcHAgPT0gIkNlbnRyb3ByaXN0aXMgc3RyaWF0YSIsCiAgICAgICAjIHJlZ2lvbiAlaW4lIGMoIk5vcnRoZWFzdCBVUyBGYWxsIiAsICJOb3J0aGVhc3QgVVMgU3ByaW5nIikpICNObyBtb3JlIHNlYXNvbnMKCgpzcHBfZGF0YSA8LSBmdW5jdGlvbihzcHApewogIAogIG5hbWVfc2F2ZSA8LSBwYXN0ZTAobXlfcGF0aCgiRCIsIlNwcC9PYnNlcnZhdGlvbiIpLCJvYnNfIixzdHJfcmVwbGFjZShzcHBbMV0sICIgIiwgIl8iKSwiLmNzdiIpCgpvY2Vhbl9kYXRhICU+JSAKICBmaWx0ZXIoc3BwID09IHNwcCwKICAgICAgIHJlZ2lvbiAlaW4lIGMoIk5vcnRoZWFzdCBVUyBGYWxsIiAsICJOb3J0aGVhc3QgVVMgU3ByaW5nIikKICAgICAgICkgJT4lIAogIHdyaXRlX2NzdiguLCBuYW1lX3NhdmUpCiAgCn0KCnNwcF9saXN0IDwtIG9jZWFuX2RhdGEgJT4lIAogIGZpbHRlcihyZWdpb24gJWluJSByZWdpb25zLAogICAgICAgICBzcHAgIT0gIk5BIikgJT4lIAogIHB1bGwoc3BwKSAlPiUgCiAgdW5pcXVlKCkKICAKCmxhcHBseShzcHBfbGlzdCwgc3BwX2RhdGEpCgoKc3Vic2V0X2RhdGEgPC0gb2NlYW5fZGF0YSAlPiUgCiAgZmlsdGVyKHNwcCA9PSAiQ2VudHJvcHJpc3RpcyBzdHJpYXRhIiwKICAgICAgIHJlZ2lvbiAlaW4lIGMoIk5vcnRoZWFzdCBVUyBGYWxsIiAsICJOb3J0aGVhc3QgVVMgU3ByaW5nIikKICAgICAgICkKCmdncGxvdCgpICsKICBnZW9tX3BvaW50KGRhdGEgPSBzdWJzZXQoc3Vic2V0X2RhdGEsIHd0Y3B1ZSA9IDAuMCksCiAgICAgICAgICAgICBhZXMoCiAgICAgICAgICAgICAgIHggPSBsb24sCiAgICAgICAgICAgICAgIHkgPSBsYXQKICAgICAgICAgICAgICksCiAgICAgICAgICAgICBjb2xvciA9ICJncmV5OTUiCiAgKSArCiAgZ2VvbV9wb2ludChkYXRhID0gc3Vic2V0KHN1YnNldF9kYXRhLCB3dGNwdWUgPiAwKSwKICAgICAgICAgICAgIGFlcygKICAgICAgICAgICAgICAgeCA9IGxvbiwKICAgICAgICAgICAgICAgeSA9IGxhdCwKICAgICAgICAgICAgICAgY29sb3IgPSBsb2cxMCh3dGNwdWUpCiAgICAgICAgICAgICApLAogICAgICAgICAgICAgc2l6ZSA9IDEKICApICsKICBzY2FsZV9jb2xvcl9kaXN0aWxsZXIocGFsZXR0ZSA9ICJTcGVjdHJhbCIsIAogICAgICAgICAgICAgICAgICAgICAgICBndWlkZV9sZWdlbmQodGl0bGUgPSAiV0NQVUUgcGVyIEhhdWwgKGxvZzEwKSIpKSArIAogIGNvb3JkX3NmKHhsaW0gPSBjKC03NiwgLTY1KSx5bGltID0gYygzNSwgNDUpKSArCiAgTXlGdW5jdGlvbnM6Om15X2dndGhlbWVfbSgpICsKICBmYWNldF93cmFwKH5yZWdpb24pCgpgYGAKCiMjIyBDb250cm9sIFBhbm5lbAoKTG9hZCByZXF1aXJlZCBkYXRhLiBOb3RlIHRoYXQgc29tZSBvZiBpdCBoYXMgYmVlbiBwcmV2aW91c2x5IGNyZWF0ZWQgCgpgYGB7ciBjb250cm9fcGFubmVsLCBldmFsID0gVCwgZWNobyA9IFR9CgojIExvYWQgZ3JpZCBkZgpncmlkX2Vlel9kZiA8LSBteV9wYXRoKCJEIiwiU3BhdGlhbCIsImdyaWRfZWV6X2RmLmNzdiIsIHJlYWQgPSBUKQoKIyBSdW4gaW50ZXJwb2xhdGlvbiBmb3IgYWxsIHllYXJzCnllYXJzIDwtIHNlcSgxOTczLDIwMTksMSkKCiMgcmVnaW9ucwpyZWdpb25zIDwtIGMoIk5vcnRoZWFzdCBVUyBGYWxsIiAsICJOb3J0aGVhc3QgVVMgU3ByaW5nIikKCiMgc3BlY2llcyBsaXN0CnNwcCA8LSBvY2Vhbl9kYXRhICU+JSAKICBmaWx0ZXIocmVnaW9uICVpbiUgcmVnaW9ucywKICAgICAgICAgc3BwICE9ICJOQSIpICU+JSAKICBwdWxsKHNwcCkgJT4lIAogIHVuaXF1ZSgpCgoKIyBEb3VibGUgY2hlY2sgcnVucwoKc3BwX3J1bnMgPC0gdGliYmxlKHRheGEgPSAobGlzdC5maWxlcyhteV9wYXRoKCJSIiwiUGFydGlhbC9JbnRlcnBvbGF0aW9uIikpKSkgJT4lCiAgbXV0YXRlKAogICAgdGF4YSA9IHN0cl9yZW1vdmUodGF4YSwgInRpZl8iKSwKICAgIHRheGEgPSBzdHJfcmVtb3ZlKHRheGEsICIuY3N2IiksCiAgICB0YXhhID0gc3RyX3JlcGxhY2UodGF4YSwgIl8iLCAiICIpCiAgKSAKCiMgTWlzc2luZyBydW5zCnNwcCA8LSB0aWJibGUodGF4YT1zcHApICU+JSAKICBhbnRpX2pvaW4oc3BwX3J1bnMpICU+JSAKICBwdWxsKHRheGEpCgoKYGBgCgojIyMgUnVuIHJvdXRpbmUKCmBgYHtyIHJ1bl9yb3V0aW5lLCBldmFsID0gVCwgZWNobyA9IFR9CgojIHNpbmdsZSBzcGVjaWVzIHJ1bgojIHJ1bl90aXMoaW5wdXRfZGF0YSA9IG9jZWFuX2RhdGEsCiMgICAgICAgICBncmlkID0gZ3JpZF9lZXpfZGYsCiMgICAgICAgICB5ZWFycyA9IHllYXJzLAojICAgICAgICAgcmVnID0gcmVnaW9ucywKIyAgICAgICAgIHRheGEgPSAiSWxsZXggaWxsZWNlYnJvc3VzIgojICkKCgojIFJ1biB0aGVtIGFsbCBpbiBwYXJhbGxlbApwYXJhbGxlbDo6bWNsYXBwbHkoc3BwLAogICAgICAgICAgICAgICAgICAgcnVuX3RpcywgCiAgICAgICAgICAgICAgICAgICBpbnB1dF9kYXRhID0gb2NlYW5fZGF0YSwKICAgICAgICAgICAgICAgICAgIGdyaWQgPSBncmlkX2Vlel9kZiwKICAgICAgICAgICAgICAgICAgIHllYXJzID0geWVhcnMsCiAgICAgICAgICAgICAgICAgICByZWcgPSByZWdpb25zCikKCgpgYGAKCgojIFJlc3VsdHMKCgpgYGB7ciBsb2FkX2RhdGF9CgojIExvYWQgaW50ZXJwb2xhdGVkIGRhdGEKIyAiQ2VudHJvcHJpc3RpcyBzdHJpYXRhIgojIApoaXN0b3JpY190aWYgPC0gbXlfcGF0aCgiUiIsIlBhcnRpYWwvSW50ZXJwb2xhdGlvbiIsInRpZl9DZW50cm9wcmlzdGlzX3N0cmlhdGEuY3N2IiwgcmVhZCA9IFQpCgojIFNwYXRpYWwgZGF0YQoKU3RhdGVzIDwtIGMoIm1haW5lIiwgIm5ldyBoYW1wc2hpcmUiLCAibWFzc2FjaHVzZXR0cyIsICJjb25uZWN0aWN1dCIsICJyaG9kZSBpc2xhbmQiLCAibmV3IHlvcmsiLCAibmV3IGplcnNleSIsICJkZWxhd2FyZSIsICJtYXJ5bGFuZCIsICJ2aXJnaW5pYSIsICJub3J0aCBjYXJvbGluYSIsInBlbm5zeWx2YW5pYSIpIAoKIyBVUyBTdGF0ZSBNYXAgKGxhbmQpCgpsYW5kX3NmIDwtIHN0X2FzX3NmKG1hcCgic3RhdGUiLCBwbG90ID0gRkFMU0UsIGZpbGwgPSBUUlVFKSkgJT4lIAogIGZpbHRlcihJRCAlaW4lIFN0YXRlcykgCgoKIyBQZXJpb2RzCnBlcmlvZHMgPC10aWJibGUoCiAgcGVyaW9kID0gYyhyZXAoImEgZWFybHkiLDEyKSwKICAgICAgICAgICAgIHJlcCgiYiBtaWQiLDEyKSwKICAgICAgICAgICAgIHJlcCgiYyBsYXRlIiwxMiksCiAgICAgICAgICAgICByZXAoImQgbm93IiwxMikKICAgICAgICAgICAgICksCiAgeWVhciA9IGMoc2VxKDE5NzIsMTk4NCwxKSwKICAgICAgICAgICAgc2VxKDE5ODUsMTk5NywxKSwKICAgICAgICAgICAgc2VxKDE5OTgsMjAxMSwxKSwKICAgICAgICAgICAgc2VxKDIwMTIsMjAxOSwxKQogICAgICAgICAgICApCiAgKQoKIyBTdGF0ZSBwYWxsZXQKCnN0YXRlX3BhbGxldCA8LSBjKHdlc19wYWxldHRlKG4gPSA1LCBuYW1lID0gIkRhcmplZWxpbmcxIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3ZXNfcGFsZXR0ZShuID0gNSwgbmFtZSA9ICJEYXJqZWVsaW5nMiIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2VzX3BhbGV0dGUobiA9IDMsIG5hbWUgPSAiUm95YWwxIikKICAgICAgICAgICAgICAgICAgKQoKCgojIHByaW50IGZvciBub3RlYm9vawpoZWFkKGhpc3RvcmljX3RpZikKYGBgCgoKIyMgUG9pbnRzCgpgYGB7ciBhcmVhX21hcF9zdGF0ZSwgZXZhbCA9IFQsIGVjaG8gPSBULCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9MTJ9CgogZGF0YV9ncmlkIDwtIGhpc3RvcmljX3RpZiAlPiUgCiAgIyBsZWZ0X2pvaW4ocGVyaW9kcykgJT4lIAogICMgZ3JvdXBfYnkoc3RhdGUsbGF0LGxvbixwZXJpb2QpICU+JSAKICBncm91cF9ieShzdGF0ZSxsYXQsbG9uLHJlZ2lvbikgJT4lIAogIHN1bW1hcmlzZShtZWFuID0gbWVhbih2YWx1ZSxuYS5ybT0gVCksIC5ncm91cHMgPSAiZHJvcCIpICU+JSAKICByZW5hbWUoSUQgPSBzdGF0ZSkKCmdncGxvdChkYXRhX2dyaWQpICsKICBnZW9tX3RpbGUoCiAgICBhZXMoCiAgICAgIHggPSBsb24sCiAgICAgIHkgPSBsYXQsCiAgICAgIGZpbGwgPSBtZWFuLAogICAgICBjb2wgPSBtZWFuCiAgICApCiAgKSArCiAgZmFjZXRfd3JhcCh+IElEICArICByZWdpb24sCiAgICAgICAgICAgICBuY29sID0gNCkgKwogIHNjYWxlX2ZpbGxfdmlyaWRpcygiTWVhbiBQcm9wb3J0aW9uIiwgYWxwaGEgPSAwLjgpICsKICBzY2FsZV9jb2xvcl92aXJpZGlzKCJNZWFuIFByb3BvcnRpb24iLCBhbHBoYSA9IDAuOCkKCgpgYGAKCiMjIE1hcAoKYGBge3IgYXJlYV9tYXAsIGV2YWwgPSBULCBlY2hvID0gVCwgZmlnLndpZHRoID0gMTB9Cgp0b3RhbF9maXRlZCA8LSBoaXN0b3JpY190aWYgJT4lIAogIGdyb3VwX2J5KHllYXIscmVnaW9uKSAlPiUgCiAgc3VtbWFyaXNlKHRvdGFsX3ZhbHVlID0gc3VtKHZhbHVlLG5hLnJtPVQpLC5ncm91cHMgPSAiZHJvcCIpCgpzdGF0ZV9maXQgPC0gaGlzdG9yaWNfdGlmICU+JSAKICBncm91cF9ieShzdGF0ZSx5ZWFyLHJlZ2lvbikgJT4lIAogIHN1bW1hcmlzZShzdGF0ZV92YWx1ZSA9IHN1bSh2YWx1ZSxuYS5ybT0gVCksIC5ncm91cHMgPSAiZHJvcCIpICU+JSAKICBsZWZ0X2pvaW4odG90YWxfZml0ZWQsCiAgICAgICAgICAgIGJ5ID0gYygieWVhciIsInJlZ2lvbiIpKSAlPiUKICBtdXRhdGUocGVyY2VudGFnZSA9IHN0YXRlX3ZhbHVlL3RvdGFsX3ZhbHVlKjEwMCkgJT4lIAogIGxlZnRfam9pbihwZXJpb2RzKSAlPiUgCiAgZ3JvdXBfYnkoSUQgPSBzdGF0ZSxwZXJpb2QscmVnaW9uKSAlPiUgCiAgc3VtbWFyaXNlKG1lYW5fcGVyID0gcm91bmQobWVhbihwZXJjZW50YWdlKSksLmdyb3VwcyA9ICJkcm9wIikKICAKIyBjaGVjayBwZXJjZW50YWdlcwojIHN0YXRlX2ZpdCAlPiUgCiMgICBncm91cF9ieShwZXJpb2QpICU+JSAKIyAgIHN1bW1hcmlzZShzdW0obWVhbl9wZXIpKQoKCmxhbmRfc2YgJT4lIAogIGxlZnRfam9pbihzdGF0ZV9maXQsCiAgICAgICAgICAgIGJ5ID0gIklEIikgJT4lIAogIGdncGxvdCgpICsKICBnZW9tX3NmKGFlcyhmaWxsID0gbWVhbl9wZXIpKSArCiAgdmlyaWRpczo6c2NhbGVfZmlsbF92aXJpZGlzKCJNZWFuIFByb3BvcnRpb24iLCBhbHBoYSA9IDAuOCkgKwogIGZhY2V0X3dyYXAofnJlZ2lvbiArIHBlcmlvZCwgbnJvdyA9IDIpICsKICBteV9nZ3RoZW1lX20oKQoKYGBgCgojIyBBcmVhIHBsb3QKClRoaXMgZ3JhcGggc2hvd3MgdGhlIHByb3BvcnRpb24gb2YgZWFjaCBTdGF0ZSBvdmVyIHRpbWUKCmBgYHtyIGFyZWFfcGxvdCwgZXZhbCA9IFQsIGVjaG8gPSBULCBmaWcuaGVpZ2h0ID0gMTAsIGZpZy53aWR0aCA9IDEwfQoKdG90YWxfZml0ZWQgPC0gaGlzdG9yaWNfdGlmICU+JSAKICBncm91cF9ieSh5ZWFyLHJlZ2lvbikgJT4lIAogIHN1bW1hcmlzZSh0b3RhbF92YWx1ZSA9IHN1bSh2YWx1ZSxuYS5ybT1UKSwuZ3JvdXBzID0gImRyb3AiKQoKIyBncm91cCBieSBzdGF0ZQpzdGF0ZV9maXQgPC0gaGlzdG9yaWNfdGlmICU+JSAKICBncm91cF9ieShzdGF0ZSx5ZWFyLHJlZ2lvbikgJT4lIAogIHN1bW1hcmlzZShzdGF0ZV92YWx1ZSA9IHN1bSh2YWx1ZSxuYS5ybT0gVCksIC5ncm91cHMgPSAiZHJvcCIpICU+JSAKICBsZWZ0X2pvaW4odG90YWxfZml0ZWQsCiAgICAgICAgICAgIGJ5ID0gYygieWVhciIsInJlZ2lvbiIpKSAlPiUKICBtdXRhdGUocGVyY2VudGFnZSA9IHN0YXRlX3ZhbHVlL3RvdGFsX3ZhbHVlKjEwMCkKCnAgPC0gZ2dwbG90KHN0YXRlX2ZpdCkgKwogIGdlb21fYXJlYSgKICAgIGFlcygKICAgICAgeCA9IHllYXIsCiAgICAgIHkgPSByb3VuZChwZXJjZW50YWdlKSwKICAgICAgZmlsbCA9IHN0YXRlCiAgICApCiAgKSArCiAgeWxhYigiUGVyY2VudGFnZSAoJSkiKSArCiAgIyB2aXJpZGlzOjpzY2FsZV9maWxsX3ZpcmlkaXMoZGlzY3JldGUgPSBULCBhbHBoYSA9IDAuOCkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHN0YXRlX3BhbGxldCkgKwogIE15RnVuY3Rpb25zOjpteV9nZ3RoZW1lX3AoKSArCiAgZmFjZXRfd3JhcCh+cmVnaW9uLCBuY29sID0gMSkKCmdncGxvdGx5KHAsCiAgICAgICAgIGR5bmFtaWNUaWNrcyA9IFRSVUUpICU+JSAKICBsYXlvdXQoaG92ZXJtb2RlID0gIngiKSAlPiUgCiAgIyBhZGRfdHJhY2UoKSAlPiUgCiAgcmFuZ2VzbGlkZXIoKQoKYGBgCiMjIEFyZWEgcGxvdCAocnVubmluZykKClRoaXMgZ3JhcGggc2hvd3MgdGhlIHByb3BvcnRpb24gb2YgZWFjaCBTdGF0ZSBzbW9vdGhlZCBvdmVyIGEgMTAgeWVhcnMgcnVubmluZyBtZWFuLiBJdCBoZWxwcyBzZWVpbmcgdGhlIHRyZW5kcyBiZXR0ZXIgKEkgVGhpbmsuLi4pCgpgYGB7ciBhcmVhX2xtX3Bsb3QsIGV2YWwgPSBULCBlY2hvID0gVCwgZmlnLmhlaWdodCA9IDEwLCBmaWcud2lkdGggPSAxMH0KCiMgZ3JvdXAgYnkgc3RhdGUKc3RhdGVfZml0IDwtIGhpc3RvcmljX3RpZiAlPiUgCiAgZ3JvdXBfYnkoc3RhdGUseWVhcixyZWdpb24sLmdyb3VwcyA9ICJkcm9wIikgJT4lIAogIHN1bW1hcmlzZShzdGF0ZV92YWx1ZSA9IHN1bSh2YWx1ZSxuYS5ybT0gVCksIC5ncm91cHMgPSAiZHJvcCIpICU+JSAKICBsZWZ0X2pvaW4odG90YWxfZml0ZWQsCiAgICAgICAgICAgIGJ5ID0gYygieWVhciIsInJlZ2lvbiIpKSAlPiUKICBtdXRhdGUocGVyY2VudGFnZSA9IHN0YXRlX3ZhbHVlL3RvdGFsX3ZhbHVlKjEwMCkgJT4lIAogIGdyb3VwX2J5KHN0YXRlLHJlZ2lvbikgJT4lIAogIG11dGF0ZShSTWVhbiA9IHpvbzo6cm9sbG1lYW4oeCA9IHBlcmNlbnRhZ2UsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgMTAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxsID0gTkEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYS5ybT1UKQogICAgKQoKIyBQbG90IG1lCnAgPC0gZ2dwbG90KHN0YXRlX2ZpdCkgKwogIGdlb21fYXJlYSgKICAgIGFlcygKICAgICAgeCA9IHllYXIsCiAgICAgIHkgPSByb3VuZChSTWVhbiksCiAgICAgIGZpbGwgPSBzdGF0ZQogICAgKQogICkgKwogIHlsYWIoIjEwIHlycyBydW5uaW5nIGF2ZXJhZ2UgKCUpIikgKwogICMgdmlyaWRpczo6c2NhbGVfZmlsbF92aXJpZGlzKGRpc2NyZXRlID0gVCwgYWxwaGEgPSAwLjgpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBzdGF0ZV9wYWxsZXQpICsKICBNeUZ1bmN0aW9uczo6bXlfZ2d0aGVtZV9wKCkgKwogIGZhY2V0X3dyYXAofnJlZ2lvbiwgbmNvbCA9IDEpCgpzdXBwcmVzc1dhcm5pbmdzKApnZ3Bsb3RseShwLAogICAgICAgICBkeW5hbWljVGlja3MgPSBUUlVFKSAlPiUgCiAgbGF5b3V0KGhvdmVybW9kZSA9ICJ4IikgJT4lIAogICMgYWRkX3RyYWNlKCkgJT4lIAogIHJhbmdlc2xpZGVyKCkKKQoKYGBgCg==